import { useState, useEffect } from 'react';
import Head from 'next/head';
import { 
  Upload, 
  Button, 
  Card, 
  Typography, 
  InputNumber, 
  Select,
  Row,
  Col,
  List, 
  Tag, 
  Divider, 
  message, 
  Progress,
  Alert,
  Space
} from 'antd';
import { 
  InboxOutlined, 
  FileOutlined, 
  DeleteOutlined, 
  DownloadOutlined,
  ScissorOutlined
} from '@ant-design/icons';
import MainLayout from '../../components/layout/MainLayout';
import JSZip from 'jszip';

const { Title, Paragraph, Text } = Typography;
const { Dragger } = Upload;
const { Option } = Select;

export default function FileSplit() {
  const [fileInfo, setFileInfo] = useState(null);
  const [splitSize, setSplitSize] = useState(10);
  const [sizeUnit, setSizeUnit] = useState('MB');
  const [isSplitting, setIsSplitting] = useState(false);
  const [progress, setProgress] = useState(0);
  const [splitResults, setSplitResults] = useState([]);
  const [resultZipUrl, setResultZipUrl] = useState('');

  const handleFileChange = (info) => {
    const { file } = info;
    
    if (file.status === 'removed') {
      setFileInfo(null);
      setSplitResults([]);
      setResultZipUrl('');
      return;
    }
    
    if (file.status !== 'uploading') {
      // 检查文件对象是否有效
      if (!file.originFileObj) {
        message.error('无效的文件对象，请重新上传');
        return;
      }
      
      // 检查文件大小
      if (file.size === 0) {
        message.error('文件大小为0，请上传有效文件');
        return;
      }
      
      // 检查Office文档类型
      const officeTypes = [
        'application/msword', // .doc
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx
        'application/vnd.ms-excel', // .xls
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
        'application/vnd.ms-powerpoint', // .ppt
        'application/vnd.openxmlformats-officedocument.presentationml.presentation' // .pptx
      ];
      
      // 获取更精确的文件类型
      let fileType = file.type || '';
      
      // 通过文件扩展名猜测类型
      if (!fileType || fileType === 'application/octet-stream') {
        const extension = file.name.split('.').pop().toLowerCase();
        const extensionTypeMap = {
          'txt': 'text/plain',
          'csv': 'text/csv',
          'log': 'text/plain',
          'md': 'text/markdown'
        };
        if (extensionTypeMap[extension]) {
          fileType = extensionTypeMap[extension];
          console.log('根据扩展名识别文件类型:', fileType);
        }
      }
      
      if (officeTypes.includes(fileType)) {
        message.warning('Office文档格式（如doc、xls、ppt）可能无法正确处理。建议先将文件转换为PDF格式。');
      }
      
      console.log('文件上传信息:', {
        name: file.name,
        type: fileType || '未知类型',
        origType: file.type || '未提供',
        size: file.size,
        isBlob: file.originFileObj instanceof Blob,
        extension: file.name.split('.').pop().toLowerCase()
      });
      
      // 只保留最新上传的一个文件
      setFileInfo({
        uid: file.uid,
        name: file.name,
        size: file.size,
        type: fileType || file.type,
        extension: file.name.split('.').pop().toLowerCase(),
        originFileObj: file.originFileObj,
        // 保存文件对象的构造函数名，用于调试
        objectType: file.originFileObj ? file.originFileObj.constructor.name : 'Unknown'
      });
      
      // 重置分割结果
      setSplitResults([]);
      setResultZipUrl('');
    }
  };
  
  const formatFileSize = (bytes) => {
    if (bytes === 0) return '0 B';
    const k = 1024;
    const sizes = ['B', 'KB', 'MB', 'GB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
  };
  
  const calculatePartCount = () => {
    if (!fileInfo) return 0;
    
    let sizeInBytes = splitSize;
    if (sizeUnit === 'KB') {
      sizeInBytes *= 1024;
    } else if (sizeUnit === 'MB') {
      sizeInBytes *= 1024 * 1024;
    }
    
    return Math.ceil(fileInfo.size / sizeInBytes);
  };
  
  const handleSplit = async () => {
    if (!fileInfo) {
      message.warning('请先上传文件');
      return;
    }
    
    // 检查文件大小
    if (fileInfo.size === 0) {
      message.warning('文件大小为0，无法分割');
      return;
    }
    
    // 计算分割大小（字节）
    let splitSizeInBytes = splitSize;
    if (sizeUnit === 'KB') {
      splitSizeInBytes *= 1024;
    } else if (sizeUnit === 'MB') {
      splitSizeInBytes *= 1024 * 1024;
    }
    
    // 如果分割大小大于文件大小，提示错误
    if (splitSizeInBytes >= fileInfo.size) {
      message.warning('分割大小必须小于文件大小');
      return;
    }
    
    setIsSplitting(true);
    setProgress(0);
    setSplitResults([]);
    setResultZipUrl('');
    
    try {
      // 检查文件对象是否有效
      if (!fileInfo.originFileObj) {
        throw new Error('无效的文件对象，请重新上传文件');
      }
      
      console.log('开始处理文件:', fileInfo.name, '类型:', fileInfo.type, '大小:', fileInfo.size, '对象类型:', fileInfo.objectType);
      
      // 创建文件读取器并设置监听
      const fileReader = new FileReader();
      
      try {
        // 获取文件内容的安全方法
        const getFileContent = async () => {
          try {
            const fileExtension = fileInfo.extension;
            const isTextFile = fileInfo.type === 'text/plain' || 
                              ['txt', 'csv', 'log', 'md'].includes(fileExtension);
            
            console.log('文件类型检测:', {
              extension: fileExtension,
              mimeType: fileInfo.type,
              isTextDetected: isTextFile
            });
            
            // 如果是Blob类型，直接使用
            if (fileInfo.originFileObj instanceof Blob) {
              console.log('文件是Blob类型，直接处理');
              return await readFileAsArrayBuffer(fileInfo.originFileObj);
            }
            
            // 特殊处理文本文件
            if (isTextFile) {
              console.log('检测到文本文件，使用特殊处理');
              try {
                // 尝试使用文本方式读取
                const textContent = await new Promise((resolve, reject) => {
                  const reader = new FileReader();
                  reader.onload = e => resolve(e.target.result);
                  reader.onerror = e => reject(e);
                  try {
                    reader.readAsText(fileInfo.originFileObj);
                  } catch (err) {
                    console.warn('文本读取失败，尝试其他方法:', err);
                    reject(err);
                  }
                });
                
                // 将文本转换为ArrayBuffer
                if (textContent) {
                  console.log('成功读取文本内容，长度:', textContent.length);
                  const encoder = new TextEncoder();
                  const uint8Array = encoder.encode(textContent);
                  return uint8Array.buffer;
                }
              } catch (textError) {
                console.warn('文本文件读取失败，尝试二进制方式:', textError);
              }
            }
            
            // 非Blob类型，尝试转换
            console.log('文件不是Blob类型，尝试转换');
            
            // 方法1: 尝试直接将原始对象作为Blob处理
            try {
              return await readFileAsArrayBuffer(fileInfo.originFileObj);
            } catch (err) {
              console.warn('直接作为Blob处理失败:', err);
            }
            
            // 方法2: 尝试从原始对象创建新的Blob
            try {
              // 检查是否有ArrayBuffer或类似数据
              let content;
              if (fileInfo.originFileObj.arrayBuffer) {
                console.log('使用arrayBuffer方法');
                content = await fileInfo.originFileObj.arrayBuffer();
              } else if (fileInfo.originFileObj.slice) {
                console.log('使用slice方法');
                content = fileInfo.originFileObj.slice(0, fileInfo.size);
              } else {
                throw new Error('文件对象没有可用的数据方法');
              }
              
              const blob = new Blob([content], { type: fileInfo.type || 'application/octet-stream' });
              return await readFileAsArrayBuffer(blob);
            } catch (err) {
              console.warn('创建新Blob失败:', err);
            }
            
            // 方法3: 尝试新的读取策略 - 特别针对text/plain等格式
            try {
              console.log('尝试替代读取策略');
              // 创建一个新的Blob，不指定具体类型
              const genericBlob = new Blob([fileInfo.originFileObj], { type: 'application/octet-stream' });
              return await readFileAsArrayBuffer(genericBlob);
            } catch (err) {
              console.warn('替代读取策略失败:', err);
            }
            
            throw new Error('无法获取文件内容，不支持的文件对象类型');
          } catch (error) {
            console.error('获取文件内容失败:', error);
            throw error;
          }
        };
        
        // 使用安全方法获取文件内容
        const arrayBuffer = await getFileContent();
        console.log('文件读取成功，数据大小:', arrayBuffer.byteLength);
        
        // 文件已成功读取为ArrayBuffer
        if (!arrayBuffer || arrayBuffer.byteLength === 0) {
          throw new Error('读取到的文件内容为空');
        }
        
        // 计算分割情况
        const totalParts = Math.ceil(arrayBuffer.byteLength / splitSizeInBytes);
        const results = [];
        
        // 创建ZIP以方便下载多个文件
        const zip = new JSZip();
        
        console.log(`开始分割文件为${totalParts}个部分，每部分约${formatFileSize(splitSizeInBytes)}`);
        
        // 分割文件
        for (let i = 0; i < totalParts; i++) {
          const start = i * splitSizeInBytes;
          const end = Math.min(start + splitSizeInBytes, arrayBuffer.byteLength);
          
          // 从arrayBuffer创建一个小块
          const chunkArrayBuffer = arrayBuffer.slice(start, end);
          
          // 创建分割文件名
          const partNumber = String(i + 1).padStart(totalParts.toString().length, '0');
          const partName = `${fileInfo.name}.part${partNumber}`;
          
          // 添加到结果列表
          results.push({
            name: partName,
            size: end - start,
            index: i
          });
          
          // 添加到ZIP - 直接使用arrayBuffer切片
          zip.file(partName, chunkArrayBuffer);
          
          // 更新进度
          setProgress(Math.round((i + 1) / totalParts * 80));
        }
        
        console.log('文件分割完成，开始创建ZIP文件');
        
        // 生成ZIP文件
        try {
          const zipContent = await zip.generateAsync(
            { 
              type: 'blob',
              compression: 'DEFLATE', 
              compressionOptions: { level: 6 }
            }, 
            (metadata) => {
              setProgress(80 + Math.round(metadata.percent / 5));
            }
          );
          
          console.log('ZIP创建完成，大小:', zipContent.size);
          
          // 创建下载链接
          const zipUrl = URL.createObjectURL(zipContent);
          
          // 更新状态
          setSplitResults(results);
          setResultZipUrl(zipUrl);
          setProgress(100);
          
          message.success(`文件已成功分割为 ${totalParts} 个部分`);
        } catch (zipError) {
          console.error('创建ZIP文件时出错:', zipError);
          throw new Error('创建ZIP文件失败，请尝试减小分割大小');
        }
      } catch (processError) {
        console.error('文件处理失败:', processError);
        throw new Error(`文件处理失败: ${processError.message || '未知错误'}`);
      }
    } catch (error) {
      console.error('文件分割错误:', error);
      message.error(error.message || '分割文件失败，请尝试其他文件');
    } finally {
      setIsSplitting(false);
    }
  };
  
  const readFileAsArrayBuffer = (file) => {
    return new Promise((resolve, reject) => {
      // 检查文件是否为null或undefined
      if (!file) {
        reject(new Error('文件对象为空'));
        return;
      }
      
      // 检查文件是否有size属性且大小为0
      if (file.size === 0) {
        reject(new Error('文件大小为0'));
        return;
      }
      
      console.log('读取文件为ArrayBuffer, 文件类型:', file.constructor.name, '文件大小:', file.size);
      
      // 尝试使用FileReader读取文件
      const reader = new FileReader();
      
      reader.onload = (e) => {
        const result = e.target.result;
        if (!result) {
          console.error('FileReader加载成功但结果为空');
          reject(new Error('文件读取结果为空'));
          return;
        }
        
        console.log('FileReader加载成功，数据大小:', result.byteLength);
        resolve(result);
      };
      
      reader.onerror = (e) => {
        console.error('FileReader错误:', e);
        reject(new Error('读取文件时出错'));
      };
      
      try {
        reader.readAsArrayBuffer(file);
      } catch (error) {
        console.error('调用readAsArrayBuffer时出错:', error);
        
        // 尝试使用备用方法
        try {
          console.log('尝试使用备用文件读取方法');
          // 尝试其他读取方式
          const backupReader = new FileReader();
          backupReader.onload = (e) => resolve(e.target.result);
          backupReader.onerror = (e) => reject(new Error('备用读取方法也失败'));
          
          // 尝试创建新的Blob再读取
          const blob = new Blob([file], { type: 'application/octet-stream' });
          backupReader.readAsArrayBuffer(blob);
        } catch (backupError) {
          reject(new Error(`读取文件失败: ${error.message}, 备用方法也失败: ${backupError.message}`));
        }
      }
    });
  };
  
  const handleDownloadAll = () => {
    if (!resultZipUrl) return;
    
    const link = document.createElement('a');
    link.href = resultZipUrl;
    link.download = `${fileInfo.name}_split.zip`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  };
  
  // 优化dragger组件的上传逻辑
  const uploadProps = {
    name: 'file',
    multiple: false,
    fileList: fileInfo ? [fileInfo] : [],
    onChange: handleFileChange,
    onRemove: () => {
      setFileInfo(null);
      setSplitResults([]);
      setResultZipUrl('');
    },
    beforeUpload: (file) => {
      // 获取扩展名
      const extension = file.name.split('.').pop().toLowerCase();
      
      console.log('上传前文件检查:', {
        name: file.name, 
        type: file.type || '未知类型', 
        extension: extension,
        size: file.size,
        lastModified: file.lastModified,
        isFile: file instanceof File,
        isBlob: file instanceof Blob
      });
      
      // 检查文件是否为空
      if (file.size === 0) {
        message.error('文件大小为0，请上传有效文件');
        return false;
      }
      
      // 检查文件大小是否过大
      const maxSize = 2 * 1024 * 1024 * 1024; // 2GB
      if (file.size > maxSize) {
        message.warning('文件超过2GB，可能无法正常处理');
      }
      
      // 检查Office文档类型
      const officeTypes = [
        'application/msword', // .doc
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx
        'application/vnd.ms-excel', // .xls
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
        'application/vnd.ms-powerpoint', // .ppt
        'application/vnd.openxmlformats-officedocument.presentationml.presentation' // .pptx
      ];
      
      // 通过扩展名检测Office文档
      const officeExtensions = ['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'];
      const isOfficeFile = officeTypes.includes(file.type) || officeExtensions.includes(extension);
      
      if (isOfficeFile) {
        message.warning('检测到Office文档格式，该类型文件可能无法正常处理。建议先转换为PDF格式。');
      }
      
      // 检测文本文件
      const textExtensions = ['txt', 'csv', 'log', 'md'];
      if (file.type === 'text/plain' || textExtensions.includes(extension)) {
        console.log('检测到文本文件:', file.name);
      }
      
      // 仅允许客户端存储，不上传到服务器
      return false;
    },
    customRequest: ({ file, onSuccess }) => {
      // 为了保证文件对象正确传递，手动调用成功回调
      console.log('自定义上传处理文件:', file.name);
      setTimeout(() => {
        onSuccess("ok", null);
      }, 0);
    }
  };

  return (
    <MainLayout>
      <Head>
        <title>文件分割 - 在线工具平台</title>
        <meta name="description" content="在线分割大文件成多个小文件，方便传输和存储" />
      </Head>
      
      <div className="page-header">
        <Title>文件分割</Title>
        <Paragraph>
          将大文件分割成小文件，方便传输和存储。所有处理在浏览器中完成，文件不会上传到服务器。
        </Paragraph>
      </div>
      
      <Row gutter={[24, 24]}>
        <Col xs={24} md={16}>
          <Card title="上传文件" bordered={false}>
            <Alert
              message="文件要求"
              description={
                <div>
                  <p>• 支持大多数文件格式，如图片、视频、音频、PDF、纯文本文件等</p>
                  <p>• <strong>不推荐上传Office文档（doc、xls、ppt等），此类文件很可能无法正常分割</strong></p>
                  <p>• 如需处理Office文档，请先将其转换为PDF格式</p>
                  <p>• 请确保上传的是完整且未损坏的文件</p>
                  <p>• 文件大小必须大于您设置的分割大小</p>
                  <p>• 浏览器限制可能导致超大文件（通常{'>'}2GB）处理失败</p>
                  <p>• 某些特殊格式或加密的文件可能无法正确处理</p>
                </div>
              }
              type="warning"
              showIcon
              style={{ marginBottom: '16px' }}
            />
            
            <Dragger {...uploadProps}>
              <p className="ant-upload-drag-icon">
                <InboxOutlined />
              </p>
              <p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
              <p className="ant-upload-hint">
                支持任意类型的单个文件
              </p>
            </Dragger>
            
            {fileInfo && (
              <div style={{ marginTop: '16px' }}>
                <Text strong>文件信息:</Text>
                <List.Item
                  key={fileInfo.uid}
                  actions={[
                    <Button 
                      key="delete" 
                      type="text" 
                      danger 
                      icon={<DeleteOutlined />}
                      onClick={() => {
                        setFileInfo(null);
                        setSplitResults([]);
                        setResultZipUrl('');
                      }}
                    >
                      删除
                    </Button>
                  ]}
                >
                  <List.Item.Meta
                    avatar={<FileOutlined style={{ fontSize: '24px', color: '#1890ff' }} />}
                    title={fileInfo.name}
                    description={`大小: ${formatFileSize(fileInfo.size)}`}
                  />
                </List.Item>
              </div>
            )}
          </Card>
        </Col>
        
        <Col xs={24} md={8}>
          <Card title="分割设置" bordered={false}>
            <Space direction="vertical" style={{ width: '100%' }}>
              <div>
                <Text>每个分割文件大小:</Text>
                <div style={{ display: 'flex', marginTop: '8px' }}>
                  <InputNumber
                    min={1}
                    value={splitSize}
                    onChange={setSplitSize}
                    style={{ flex: 1 }}
                  />
                  <Select 
                    value={sizeUnit} 
                    onChange={setSizeUnit}
                    style={{ width: '80px', marginLeft: '8px' }}
                  >
                    <Option value="KB">KB</Option>
                    <Option value="MB">MB</Option>
                  </Select>
                </div>
              </div>
              
              {fileInfo && (
                <Alert
                  message="分割预览"
                  description={
                    <div>
                      <p>文件将被分割为 <Tag color="blue">{calculatePartCount()}</Tag> 个部分</p>
                      <p>每个部分大小约为 <Tag color="green">{splitSize} {sizeUnit}</Tag></p>
                    </div>
                  }
                  type="info"
                />
              )}
              
              <Button 
                type="primary" 
                icon={<ScissorOutlined />}
                onClick={handleSplit}
                loading={isSplitting}
                disabled={!fileInfo}
                block
              >
                开始分割
              </Button>
            </Space>
          </Card>
        </Col>
      </Row>
      
      {isSplitting && (
        <Card style={{ marginTop: '24px' }}>
          <Progress percent={progress} status="active" />
          <div style={{ textAlign: 'center', marginTop: '8px' }}>
            <Text type="secondary">正在分割文件，请稍候...</Text>
          </div>
        </Card>
      )}
      
      {splitResults.length > 0 && (
        <Card 
          title="分割结果" 
          extra={
            <Button 
              type="primary" 
              icon={<DownloadOutlined />} 
              onClick={handleDownloadAll}
            >
              下载所有文件
            </Button>
          }
          style={{ marginTop: '24px' }}
        >
          <List
            bordered
            dataSource={splitResults}
            renderItem={item => (
              <List.Item>
                <List.Item.Meta
                  avatar={<FileOutlined style={{ fontSize: '24px', color: '#52c41a' }} />}
                  title={item.name}
                  description={`大小: ${formatFileSize(item.size)}`}
                />
              </List.Item>
            )}
          />
          
          <Divider />
          
          <Alert
            message="如何合并文件"
            description={
              <div>
                <p>在Windows系统中，您可以使用以下命令行合并文件:</p>
                <pre style={{ background: '#f5f5f5', padding: '8px', borderRadius: '4px' }}>
                  copy /b file.part* original_file
                </pre>
                <p>在Linux或Mac系统中，您可以使用以下命令行合并文件:</p>
                <pre style={{ background: '#f5f5f5', padding: '8px', borderRadius: '4px' }}>
                  cat file.part* {'>'} original_file
                </pre>
              </div>
            }
            type="info"
            showIcon
          />
        </Card>
      )}
    </MainLayout>
  );
} 